CREATE OR REPLACE EDITIONABLE PACKAGE BODY "SCOTT"."PKG_MODEL_WEEK" is

  /*------------------- 计算周线级别布林带跌破下轨后，MACD金叉的算法 ---------------------*/
  procedure CAL_MDL_WEEK_BOLL_MACD_G_C is
    -- 股票代码
    v_code varchar2(50);
    -- 日期
    v_date date := to_date('1997-01-01', 'yyyy-mm-dd');
    -- 行数
    v_row_num number;
    -- 是否有金叉，0表示没有，1表示有
    v_gold_cross number := 0;
    -- 累计盈利
    v_pre_acc_profit_loss number := 100;
    -- stock_week表的记录
    row_stock_week        stock_week%rowtype;
    row_first_stock_week  stock_week%rowtype;
    row_second_stock_week stock_week%rowtype;
    -- stock_transaction_data表的记录
    row_stock_transaction_data stock_transaction_data%rowtype;
    row_macd_dead_cross        stock_transaction_data%rowtype;
    row_last_std               stock_transaction_data%rowtype;
    -- 返回股票代码
    cursor cur_stock_code is
      select distinct t.code_ from stock_week t; -- where t.code_ = '603759';
    -- 某一只股票的最低价跌破了布林带下轨
    cursor cur_stock_week_dn is
      select *
        from stock_week t
       where t.lowest_price < t.dn_
         and t.code_ = v_code
         and t.end_date > v_date
       order by t.begin_date asc;
    -- 某一只股票当前星期的记录，和下一个星期的记录
    cursor cur_two_stock_week is
      select *
        from (select *
                from stock_week t
               where t.code_ = v_code
                 and t.begin_date >= row_stock_week.begin_date
               order by t.begin_date asc)
       where rownum <= 2;
    -- 某一只股票在某个交易日之后和某个交易日之前的交易记录
    cursor cur_stock_transaction_data is
      select *
        from stock_transaction_data_all t
       where t.code_ = row_stock_week.code_
         and t.date_ > row_first_stock_week.end_date
         and t.date_ <= row_second_stock_week.end_date
       order by t.date_ asc;
  begin
    open cur_stock_code;
    loop
      fetch cur_stock_code
        into v_code;
      exit when cur_stock_code%notfound;
    
      -- 重置
      v_pre_acc_profit_loss := 100;
      v_date                := to_date('1997-01-01', 'yyyy-mm-dd');
    
      open cur_stock_week_dn;
      loop
        fetch cur_stock_week_dn
          into row_stock_week;
        exit when cur_stock_week_dn%notfound;
        if row_stock_week.end_date < v_date then
          continue;
        end if;
      
        -- 如果不足两行，则说明这只股票已经计算完成
        select count(*)
          into v_row_num
          from (select *
                  from stock_week t
                 where t.code_ = v_code
                   and t.begin_date >= row_stock_week.begin_date
                 order by t.begin_date asc)
         where rownum <= 2;
        if v_row_num != 2 then
          exit;
        end if;
        -- 重置
        v_gold_cross          := 0;
        row_first_stock_week  := null;
        row_second_stock_week := null;
        -- 当前周和下一周
        for cur in cur_two_stock_week loop
          if row_first_stock_week.id_ is null then
            row_first_stock_week := cur;
          else
            row_second_stock_week := cur;
          end if;
        end loop;
        -- 如果下一周的最低价比当前周的最低价低，则放弃当前周
        if row_first_stock_week.lowest_price >
           row_second_stock_week.lowest_price then
          continue;
        end if;
      
        -- 判断下一周是否有MACD金叉，如果没有就继续寻找下一个最低价跌破布林带下轨的记录
        -- 注意此处只判断一周内是否有MACD金叉，这样比较符合实盘交易的情况
        open cur_stock_transaction_data;
        loop
          fetch cur_stock_transaction_data
            into row_stock_transaction_data;
          exit when cur_stock_transaction_data%notfound;
          -- 金叉，买入
          -- 查找前一天的交易记录
          select *
            into row_last_std
            from (select *
                    from stock_transaction_data_all t
                   where t.code_ = row_stock_transaction_data.code_
                     and t.date_ < row_stock_transaction_data.date_
                   order by t.date_ desc)
           where rownum <= 1;
          if row_last_std.dif <= row_last_std.dea and
             row_stock_transaction_data.dif >
             row_stock_transaction_data.dea then
            v_gold_cross := 1;
            exit;
          end if;
        end loop;
        close cur_stock_transaction_data;
        if v_gold_cross = 0 then
          continue;
        end if;
      
        -- 如果金叉出现，则开始寻找MACD死叉的记录
        if v_gold_cross = 1 then
          -- 死叉，卖出
          -- 某一只股票在某个交易日之后的第一个MACD死叉。如果没有就从下一个最低价跌破布林带下轨的记录开始
          begin
            select *
              into row_macd_dead_cross
              from (select *
                      from stock_transaction_data_all t
                     where t.code_ = row_stock_transaction_data.code_
                       and t.date_ > row_stock_transaction_data.date_
                       and t.dif < t.dea
                     order by t.date_ asc)
             where rownum <= 1;
          EXCEPTION
            WHEN others THEN
              row_macd_dead_cross := null;
              exit;
          end;
        
          -- 获取mdl_boll_macd_gold_cross表中，某只股票的上一个交易记录
          /*begin
            select *
              into v_pre_acc_profit_loss
              from (select t.accumulative_profit_loss
                      from mdl_boll_macd_gold_cross t
                     where t.stock_code = v_code
                       and t.buy_date < row_stock_transaction_data.date_
                       and t.sell_date < row_macd_dead_cross.date_
                     order by t.buy_date desc)
             where rownum <= 1;
          EXCEPTION
            WHEN others THEN
              v_pre_acc_profit_loss := 100;
          end;*/
        
          -- 添加记录
          v_pre_acc_profit_loss := v_pre_acc_profit_loss * (1 +
                                   (row_macd_dead_cross.close_price -
                                   row_stock_transaction_data.close_price) /
                                   row_stock_transaction_data.close_price);
          insert into mdl_week_boll_macd_gold_cross
            (STOCK_CODE,
             BUY_DATE,
             BUY_PRICE,
             ACCUMULATIVE_PROFIT_LOSS,
             PROFIT_LOSS,
             SELL_DATE,
             SELL_PRICE)
          values
            (row_stock_transaction_data.code_,
             row_stock_transaction_data.date_,
             row_stock_transaction_data.close_price,
             v_pre_acc_profit_loss,
             (row_macd_dead_cross.close_price -
             row_stock_transaction_data.close_price) /
             row_stock_transaction_data.close_price * 100,
             row_macd_dead_cross.date_,
             row_macd_dead_cross.close_price);
        
          -- 重置
          v_gold_cross := 0;
          v_date       := row_macd_dead_cross.date_;
        end if;
      
      end loop;
      close cur_stock_week_dn;
    
    end loop;
    close cur_stock_code;
    commit;
  end CAL_MDL_WEEK_BOLL_MACD_G_C;

  /*--------------- 计算周线级别布林带跌破下轨后，close_price金叉ma5的算法 -----------------*/
  procedure CAL_MDL_WEEK_BOLL_C_P_MA5_G_C is
    -- 股票代码
    v_code varchar2(50);
    -- 日期
    v_date date := to_date('1997-01-01', 'yyyy-mm-dd');
    -- 行数
    v_row_num number;
    -- 是否有金叉，0表示没有，1表示有
    v_gold_cross number := 0;
    -- 累计盈利
    v_pre_acc_profit_loss number := 100;
    -- stock_week表的记录
    row_stock_week        stock_week%rowtype;
    row_first_stock_week  stock_week%rowtype;
    row_second_stock_week stock_week%rowtype;
    -- stock_transaction_data表的记录
    row_stock_transaction_data     stock_transaction_data%rowtype;
    row_close_price_ma5_dead_cross stock_transaction_data%rowtype;
    row_last_std                   stock_transaction_data%rowtype;
    -- 返回股票代码
    cursor cur_stock_code is
      select distinct t.code_ from stock_week t; -- where t.code_ = '603759';
    -- 某一只股票的最低价跌破了布林带下轨
    cursor cur_stock_week_dn is
      select *
        from stock_week t
       where t.lowest_price < t.dn_
         and t.code_ = v_code
         and t.end_date > v_date
       order by t.begin_date asc;
    -- 某一只股票当前星期的记录，和下一个星期的记录
    cursor cur_two_stock_week is
      select *
        from (select *
                from stock_week t
               where t.code_ = v_code
                 and t.begin_date >= row_stock_week.begin_date
               order by t.begin_date asc)
       where rownum <= 2;
    -- 某一只股票在某个交易日之后和某个交易日之前的交易记录
    cursor cur_stock_transaction_data is
      select *
        from stock_transaction_data_all t
       where t.code_ = row_stock_week.code_
         and t.date_ > row_first_stock_week.end_date
         and t.date_ <= row_second_stock_week.end_date
       order by t.date_ asc;
  begin
    open cur_stock_code;
    loop
      fetch cur_stock_code
        into v_code;
      exit when cur_stock_code%notfound;
    
      -- 重置
      v_pre_acc_profit_loss := 100;
      v_date                := to_date('1997-01-01', 'yyyy-mm-dd');
    
      open cur_stock_week_dn;
      loop
        fetch cur_stock_week_dn
          into row_stock_week;
        exit when cur_stock_week_dn%notfound;
        if row_stock_week.end_date < v_date then
          continue;
        end if;
      
        -- 如果不足两行，则说明这只股票已经计算完成
        select count(*)
          into v_row_num
          from (select *
                  from stock_week t
                 where t.code_ = v_code
                   and t.begin_date >= row_stock_week.begin_date
                 order by t.begin_date asc)
         where rownum <= 2;
        if v_row_num != 2 then
          exit;
        end if;
        -- 重置
        v_gold_cross          := 0;
        row_first_stock_week  := null;
        row_second_stock_week := null;
        -- 当前周和下一周
        for cur in cur_two_stock_week loop
          if row_first_stock_week.id_ is null then
            row_first_stock_week := cur;
          else
            row_second_stock_week := cur;
          end if;
        end loop;
        -- 如果下一周的最低价比当前周的最低价低，则放弃当前周
        if row_first_stock_week.lowest_price >
           row_second_stock_week.lowest_price then
          continue;
        end if;
      
        -- 判断下一周是否有close_price金叉ma5，如果没有就继续寻找下一个最低价跌破布林带下轨的记录
        -- 注意此处只判断一周内是否有close_price金叉ma5，这样比较符合实盘交易的情况
        open cur_stock_transaction_data;
        loop
          fetch cur_stock_transaction_data
            into row_stock_transaction_data;
          exit when cur_stock_transaction_data%notfound;
          -- 金叉，买入
          -- 查找前一天的交易记录
          select *
            into row_last_std
            from (select *
                    from stock_transaction_data_all t
                   where t.code_ = row_stock_transaction_data.code_
                     and t.date_ < row_stock_transaction_data.date_
                   order by t.date_ desc)
           where rownum <= 1;
          if row_last_std.close_price <= row_last_std.ma5 and
             row_stock_transaction_data.close_price >
             row_stock_transaction_data.ma5 then
            v_gold_cross := 1;
            exit;
          end if;
        end loop;
        close cur_stock_transaction_data;
        if v_gold_cross = 0 then
          continue;
        end if;
      
        -- 如果金叉出现，则开始寻找close_price死叉ma5的记录
        if v_gold_cross = 1 then
          -- 死叉，卖出
          -- 某一只股票在某个交易日之后的第一个close_price死叉ma5。如果没有就从下一个最低价跌破布林带下轨的记录开始
          begin
            select *
              into row_close_price_ma5_dead_cross
              from (select *
                      from stock_transaction_data_all t
                     where t.code_ = row_stock_transaction_data.code_
                       and t.date_ > row_stock_transaction_data.date_
                       and t.close_price < t.ma5
                     order by t.date_ asc)
             where rownum <= 1;
          EXCEPTION
            WHEN others THEN
              row_close_price_ma5_dead_cross := null;
              exit;
          end;
        
          -- 获取mdl_boll_macd_gold_cross表中，某只股票的上一个交易记录
          /*begin
            select *
              into v_pre_acc_profit_loss
              from (select t.accumulative_profit_loss
                      from mdl_boll_macd_gold_cross t
                     where t.stock_code = v_code
                       and t.buy_date < row_stock_transaction_data.date_
                       and t.sell_date < row_macd_dead_cross.date_
                     order by t.buy_date desc)
             where rownum <= 1;
          EXCEPTION
            WHEN others THEN
              v_pre_acc_profit_loss := 100;
          end;*/
        
          -- 添加记录
          v_pre_acc_profit_loss := v_pre_acc_profit_loss * (1 +
                                   (row_close_price_ma5_dead_cross.close_price -
                                   row_stock_transaction_data.close_price) /
                                   row_stock_transaction_data.close_price);
          insert into mdl_week_boll_c_p_ma5_g_c
            (STOCK_CODE,
             BUY_DATE,
             BUY_PRICE,
             ACCUMULATIVE_PROFIT_LOSS,
             PROFIT_LOSS,
             SELL_DATE,
             SELL_PRICE)
          values
            (row_stock_transaction_data.code_,
             row_stock_transaction_data.date_,
             row_stock_transaction_data.close_price,
             v_pre_acc_profit_loss,
             (row_close_price_ma5_dead_cross.close_price -
             row_stock_transaction_data.close_price) /
             row_stock_transaction_data.close_price * 100,
             row_close_price_ma5_dead_cross.date_,
             row_close_price_ma5_dead_cross.close_price);
        
          -- 重置
          v_gold_cross := 0;
          v_date       := row_close_price_ma5_dead_cross.date_;
        end if;
      
      end loop;
      close cur_stock_week_dn;
    
    end loop;
    close cur_stock_code;
    commit;
  end CAL_MDL_WEEK_BOLL_C_P_MA5_G_C;

  /*--------------- 计算周线级别布林带跌破下轨后，hei_kin_ashi上升趋势的算法 ---------------*/
  procedure CAL_MDL_WEEK_BOLL_H_K_A_U_D is
    -- 股票代码
    v_code varchar2(50);
    -- 日期
    v_date date := to_date('1997-01-01', 'yyyy-mm-dd');
    -- 行数
    v_row_num number;
    -- 是否有金叉，0表示没有，1表示有
    v_gold_cross number := 0;
    -- 累计盈利
    v_pre_acc_profit_loss number := 100;
    -- stock_week表的记录
    row_stock_week        stock_week%rowtype;
    row_first_stock_week  stock_week%rowtype;
    row_second_stock_week stock_week%rowtype;
    -- stock_transaction_data表的记录
    row_stock_transaction_data stock_transaction_data%rowtype;
    row_hei_kin_ashi_up_down   stock_transaction_data%rowtype;
    row_last_std               stock_transaction_data%rowtype;
    -- 返回股票代码
    cursor cur_stock_code is
      select distinct t.code_ from stock_week t; -- where t.code_ = '603759';
    -- 某一只股票的最低价跌破了布林带下轨
    cursor cur_stock_week_dn is
      select *
        from stock_week t
       where t.lowest_price < t.dn_
         and t.code_ = v_code
         and t.end_date > v_date
       order by t.begin_date asc;
    -- 某一只股票当前星期的记录，和下一个星期的记录
    cursor cur_two_stock_week is
      select *
        from (select *
                from stock_week t
               where t.code_ = v_code
                 and t.begin_date >= row_stock_week.begin_date
               order by t.begin_date asc)
       where rownum <= 2;
    -- 某一只股票在某个交易日之后和某个交易日之前的交易记录
    cursor cur_stock_transaction_data is
      select *
        from stock_transaction_data_all t
       where t.code_ = row_stock_week.code_
         and t.date_ > row_first_stock_week.end_date
         and t.date_ <= row_second_stock_week.end_date
       order by t.date_ asc;
  begin
    open cur_stock_code;
    loop
      fetch cur_stock_code
        into v_code;
      exit when cur_stock_code%notfound;
    
      -- 重置
      v_pre_acc_profit_loss := 100;
      v_date                := to_date('1997-01-01', 'yyyy-mm-dd');
    
      open cur_stock_week_dn;
      loop
        fetch cur_stock_week_dn
          into row_stock_week;
        exit when cur_stock_week_dn%notfound;
        if row_stock_week.end_date < v_date then
          continue;
        end if;
      
        -- 如果不足两行，则说明这只股票已经计算完成
        select count(*)
          into v_row_num
          from (select *
                  from stock_week t
                 where t.code_ = v_code
                   and t.begin_date >= row_stock_week.begin_date
                 order by t.begin_date asc)
         where rownum <= 2;
        if v_row_num != 2 then
          exit;
        end if;
        -- 重置
        v_gold_cross          := 0;
        row_first_stock_week  := null;
        row_second_stock_week := null;
        -- 当前周和下一周
        for cur in cur_two_stock_week loop
          if row_first_stock_week.id_ is null then
            row_first_stock_week := cur;
          else
            row_second_stock_week := cur;
          end if;
        end loop;
        -- 如果下一周的最低价比当前周的最低价低，则放弃当前周
        if row_first_stock_week.lowest_price >
           row_second_stock_week.lowest_price then
          continue;
        end if;
      
        -- 判断下一周是否有hei_kin_ashi上升趋势，如果没有就继续寻找下一个最低价跌破布林带下轨的记录
        -- 注意此处只判断一周内是否有hei_kin_ashi上升趋势，这样比较符合实盘交易的情况
        open cur_stock_transaction_data;
        loop
          fetch cur_stock_transaction_data
            into row_stock_transaction_data;
          exit when cur_stock_transaction_data%notfound;
          -- 金叉，买入
          -- 查找前一天的交易记录
          select *
            into row_last_std
            from (select *
                    from stock_transaction_data_all t
                   where t.code_ = row_stock_transaction_data.code_
                     and t.date_ < row_stock_transaction_data.date_
                   order by t.date_ desc)
           where rownum <= 1;
          if row_last_std.ha_close_price < row_last_std.ha_open_price and
             row_stock_transaction_data.ha_close_price >=
             row_stock_transaction_data.ha_open_price then
            v_gold_cross := 1;
            exit;
          end if;
        end loop;
        close cur_stock_transaction_data;
        if v_gold_cross = 0 then
          continue;
        end if;
      
        -- 如果hei_kin_ashi上升趋势出现，则开始寻找hei_kin_ashi下降趋势的记录
        if v_gold_cross = 1 then
          -- 死叉，卖出
          -- 某一只股票在某个交易日之后的第一个hei_kin_ashi下降趋势。如果没有就从下一个最低价跌破布林带下轨的记录开始
          begin
            select *
              into row_hei_kin_ashi_up_down
              from (select *
                      from stock_transaction_data_all t
                     where t.code_ = row_stock_transaction_data.code_
                       and t.date_ > row_stock_transaction_data.date_
                       and t.ha_close_price < t.ha_open_price
                     order by t.date_ asc)
             where rownum <= 1;
          EXCEPTION
            WHEN others THEN
              row_hei_kin_ashi_up_down := null;
              exit;
          end;
        
          -- 获取mdl_boll_macd_gold_cross表中，某只股票的上一个交易记录
          /*begin
            select *
              into v_pre_acc_profit_loss
              from (select t.accumulative_profit_loss
                      from mdl_boll_macd_gold_cross t
                     where t.stock_code = v_code
                       and t.buy_date < row_stock_transaction_data.date_
                       and t.sell_date < row_macd_dead_cross.date_
                     order by t.buy_date desc)
             where rownum <= 1;
          EXCEPTION
            WHEN others THEN
              v_pre_acc_profit_loss := 100;
          end;*/
        
          -- 添加记录
          v_pre_acc_profit_loss := v_pre_acc_profit_loss * (1 +
                                   (row_hei_kin_ashi_up_down.close_price -
                                   row_stock_transaction_data.close_price) /
                                   row_stock_transaction_data.close_price);
          insert into mdl_week_boll_H_K_A_UP_DOWN
            (STOCK_CODE,
             BUY_DATE,
             BUY_PRICE,
             ACCUMULATIVE_PROFIT_LOSS,
             PROFIT_LOSS,
             SELL_DATE,
             SELL_PRICE)
          values
            (row_stock_transaction_data.code_,
             row_stock_transaction_data.date_,
             row_stock_transaction_data.close_price,
             v_pre_acc_profit_loss,
             (row_hei_kin_ashi_up_down.close_price -
             row_stock_transaction_data.close_price) /
             row_stock_transaction_data.close_price * 100,
             row_hei_kin_ashi_up_down.date_,
             row_hei_kin_ashi_up_down.close_price);
        
          -- 重置
          v_gold_cross := 0;
          v_date       := row_hei_kin_ashi_up_down.date_;
        end if;
      
      end loop;
      close cur_stock_week_dn;
    
    end loop;
    close cur_stock_code;
    commit;
  end CAL_MDL_WEEK_BOLL_H_K_A_U_D;

  /*--------------- 计算周线级别布林带跌破下轨后，kd金叉的算法 ---------------*/
  procedure CAL_MDL_WEEK_BOLL_KD_G_C is
    -- 股票代码
    v_code varchar2(50);
    -- 日期
    v_date date := to_date('1997-01-01', 'yyyy-mm-dd');
    -- 行数
    v_row_num number;
    -- 是否有金叉，0表示没有，1表示有
    v_gold_cross number := 0;
    -- 累计盈利
    v_pre_acc_profit_loss number := 100;
    -- stock_week表的记录
    row_stock_week        stock_week%rowtype;
    row_first_stock_week  stock_week%rowtype;
    row_second_stock_week stock_week%rowtype;
    -- stock_transaction_data表的记录
    row_stock_transaction_data stock_transaction_data%rowtype;
    row_kd_gold_cross          stock_transaction_data%rowtype;
    row_last_std               stock_transaction_data%rowtype;
    -- 返回股票代码
    cursor cur_stock_code is
      select distinct t.code_ from stock_week t; -- where t.code_ = '603759';
    -- 某一只股票的最低价跌破了布林带下轨
    cursor cur_stock_week_dn is
      select *
        from stock_week t
       where t.lowest_price < t.dn_
         and t.code_ = v_code
         and t.end_date > v_date
       order by t.begin_date asc;
    -- 某一只股票当前星期的记录，和下一个星期的记录
    cursor cur_two_stock_week is
      select *
        from (select *
                from stock_week t
               where t.code_ = v_code
                 and t.begin_date >= row_stock_week.begin_date
               order by t.begin_date asc)
       where rownum <= 2;
    -- 某一只股票在某个交易日之后和某个交易日之前的交易记录
    cursor cur_stock_transaction_data is
      select *
        from stock_transaction_data_all t
       where t.code_ = row_stock_week.code_
         and t.date_ > row_first_stock_week.end_date
         and t.date_ <= row_second_stock_week.end_date
       order by t.date_ asc;
  begin
    open cur_stock_code;
    loop
      fetch cur_stock_code
        into v_code;
      exit when cur_stock_code%notfound;
    
      -- 重置
      v_pre_acc_profit_loss := 100;
      v_date                := to_date('1997-01-01', 'yyyy-mm-dd');
    
      open cur_stock_week_dn;
      loop
        fetch cur_stock_week_dn
          into row_stock_week;
        exit when cur_stock_week_dn%notfound;
        if row_stock_week.end_date < v_date then
          continue;
        end if;
      
        -- 如果不足两行，则说明这只股票已经计算完成
        select count(*)
          into v_row_num
          from (select *
                  from stock_week t
                 where t.code_ = v_code
                   and t.begin_date >= row_stock_week.begin_date
                 order by t.begin_date asc)
         where rownum <= 2;
        if v_row_num != 2 then
          exit;
        end if;
        -- 重置
        v_gold_cross          := 0;
        row_first_stock_week  := null;
        row_second_stock_week := null;
        -- 当前周和下一周
        for cur in cur_two_stock_week loop
          if row_first_stock_week.id_ is null then
            row_first_stock_week := cur;
          else
            row_second_stock_week := cur;
          end if;
        end loop;
        -- 如果下一周的最低价比当前周的最低价高，则放弃当前周
        if row_first_stock_week.lowest_price >
           row_second_stock_week.lowest_price then
          continue;
        end if;
      
        -- 判断下一周是否有kd金叉，如果没有就继续寻找下一个最低价突破布林带上轨的记录
        -- 注意此处只判断一周内是否有kd金叉，这样比较符合实盘交易的情况
        open cur_stock_transaction_data;
        loop
          fetch cur_stock_transaction_data
            into row_stock_transaction_data;
          exit when cur_stock_transaction_data%notfound;
          -- 金叉，买入
          -- 查找前一天的交易记录
          select *
            into row_last_std
            from (select *
                    from stock_transaction_data_all t
                   where t.code_ = row_stock_transaction_data.code_
                     and t.date_ < row_stock_transaction_data.date_
                   order by t.date_ desc)
           where rownum <= 1;
          if row_last_std.k <= row_last_std.d and
             row_stock_transaction_data.k > row_stock_transaction_data.d then
            v_gold_cross := 1;
            exit;
          end if;
        end loop;
        close cur_stock_transaction_data;
        if v_gold_cross = 0 then
          continue;
        end if;
      
        -- 如果kd死叉出现，则开始寻找kd死叉的记录
        if v_gold_cross = 1 then
          -- 死叉，卖出
          -- 某一只股票在某个交易日之后的第一个kd死叉。如果没有就从下一个最低价跌破布林带下轨的记录开始
          begin
            select *
              into row_kd_gold_cross
              from (select *
                      from stock_transaction_data_all t
                     where t.code_ = row_stock_transaction_data.code_
                       and t.date_ > row_stock_transaction_data.date_
                       and t.k < t.d
                     order by t.date_ asc)
             where rownum <= 1;
          EXCEPTION
            WHEN others THEN
              row_kd_gold_cross := null;
              exit;
          end;
        
          -- 获取mdl_boll_macd_gold_cross表中，某只股票的上一个交易记录
          /*begin
            select *
              into v_pre_acc_profit_loss
              from (select t.accumulative_profit_loss
                      from mdl_boll_macd_gold_cross t
                     where t.stock_code = v_code
                       and t.buy_date < row_stock_transaction_data.date_
                       and t.sell_date < row_macd_dead_cross.date_
                     order by t.buy_date desc)
             where rownum <= 1;
          EXCEPTION
            WHEN others THEN
              v_pre_acc_profit_loss := 100;
          end;*/
        
          -- 添加记录
          v_pre_acc_profit_loss := v_pre_acc_profit_loss * (1 +
                                   (row_kd_gold_cross.close_price -
                                   row_stock_transaction_data.close_price) /
                                   row_stock_transaction_data.close_price);
          insert into mdl_week_boll_kd_gold_cross
            (STOCK_CODE,
             BUY_DATE,
             BUY_PRICE,
             ACCUMULATIVE_PROFIT_LOSS,
             PROFIT_LOSS,
             SELL_DATE,
             SELL_PRICE)
          values
            (row_stock_transaction_data.code_,
             row_stock_transaction_data.date_,
             row_stock_transaction_data.close_price,
             v_pre_acc_profit_loss,
             (row_kd_gold_cross.close_price -
             row_stock_transaction_data.close_price) /
             row_stock_transaction_data.close_price * 100,
             row_kd_gold_cross.date_,
             row_kd_gold_cross.close_price);
        
          -- 重置
          v_gold_cross := 0;
          v_date       := row_kd_gold_cross.date_;
        end if;
      
      end loop;
      close cur_stock_week_dn;
    
    end loop;
    close cur_stock_code;
    commit;
  end CAL_MDL_WEEK_BOLL_KD_G_C;

  /*------------------- 计算周线级别布林带突破上轨后，MACD死叉的算法 ---------------------*/
  procedure CAL_MDL_WEEK_BOLL_MACD_D_C is
    -- 股票代码
    v_code varchar2(50);
    -- 日期
    v_date date := to_date('1997-01-01', 'yyyy-mm-dd');
    -- 行数
    v_row_num number;
    -- 是否有死叉，0表示没有，1表示有
    v_dead_cross number := 0;
    -- 累计盈利
    v_pre_acc_profit_loss number := 100;
    -- stock_week表的记录
    row_stock_week        stock_week%rowtype;
    row_first_stock_week  stock_week%rowtype;
    row_second_stock_week stock_week%rowtype;
    -- stock_transaction_data表的记录
    row_stock_transaction_data stock_transaction_data%rowtype;
    row_macd_gold_cross        stock_transaction_data%rowtype;
    row_last_std               stock_transaction_data%rowtype;
    -- 返回股票代码
    cursor cur_stock_code is
      select distinct t.code_ from stock_week t; -- where t.code_ = '603759';
    -- 某一只股票的最高价突破了布林带上轨
    cursor cur_stock_week_up is
      select *
        from stock_week t
       where t.highest_price > t.up
         and t.code_ = v_code
         and t.end_date > v_date
       order by t.begin_date asc;
    -- 某一只股票当前星期的记录，和下一个星期的记录
    cursor cur_two_stock_week is
      select *
        from (select *
                from stock_week t
               where t.code_ = v_code
                 and t.begin_date >= row_stock_week.begin_date
               order by t.begin_date asc)
       where rownum <= 2;
    -- 某一只股票在某个交易日之后和某个交易日之前的交易记录
    cursor cur_stock_transaction_data is
      select *
        from stock_transaction_data_all t
       where t.code_ = row_stock_week.code_
         and t.date_ > row_first_stock_week.end_date
         and t.date_ <= row_second_stock_week.end_date
       order by t.date_ asc;
  begin
    open cur_stock_code;
    loop
      fetch cur_stock_code
        into v_code;
      exit when cur_stock_code%notfound;
    
      -- 重置
      v_pre_acc_profit_loss := 100;
      v_date                := to_date('1997-01-01', 'yyyy-mm-dd');
    
      open cur_stock_week_up;
      loop
        fetch cur_stock_week_up
          into row_stock_week;
        exit when cur_stock_week_up%notfound;
        if row_stock_week.end_date < v_date then
          continue;
        end if;
      
        -- 如果不足两行，则说明这只股票已经计算完成
        select count(*)
          into v_row_num
          from (select *
                  from stock_week t
                 where t.code_ = v_code
                   and t.begin_date >= row_stock_week.begin_date
                 order by t.begin_date asc)
         where rownum <= 2;
        if v_row_num != 2 then
          exit;
        end if;
        -- 重置
        v_dead_cross          := 0;
        row_first_stock_week  := null;
        row_second_stock_week := null;
        -- 当前周和下一周
        for cur in cur_two_stock_week loop
          if row_first_stock_week.id_ is null then
            row_first_stock_week := cur;
          else
            row_second_stock_week := cur;
          end if;
        end loop;
        -- 如果下一周的最高价比当前周的最高价低，则放弃当前周
        if row_first_stock_week.highest_price <
           row_second_stock_week.highest_price then
          continue;
        end if;
      
        -- 判断下一周是否有MACD死叉，如果没有就继续寻找下一个最高价突破布林带上轨的记录
        -- 注意此处只判断一周内是否有MACD死叉，这样比较符合实盘交易的情况
        open cur_stock_transaction_data;
        loop
          fetch cur_stock_transaction_data
            into row_stock_transaction_data;
          exit when cur_stock_transaction_data%notfound;
          -- 死叉，卖出
          -- 查找前一天的交易记录
          select *
            into row_last_std
            from (select *
                    from stock_transaction_data_all t
                   where t.code_ = row_stock_transaction_data.code_
                     and t.date_ < row_stock_transaction_data.date_
                   order by t.date_ desc)
           where rownum <= 1;
          if row_last_std.dif <= row_last_std.dea and
             row_stock_transaction_data.dif <
             row_stock_transaction_data.dea then
            v_dead_cross := 1;
            exit;
          end if;
        end loop;
        close cur_stock_transaction_data;
        if v_dead_cross = 0 then
          continue;
        end if;
      
        -- 如果死叉出现，则开始寻找MACD死叉的记录
        if v_dead_cross = 1 then
          -- 金叉，买入
          -- 某一只股票在某个交易日之后的第一个MACD金叉。如果没有就从下一个最高价突破布林带上轨轨的记录开始
          begin
            select *
              into row_macd_gold_cross
              from (select *
                      from stock_transaction_data_all t
                     where t.code_ = row_stock_transaction_data.code_
                       and t.date_ > row_stock_transaction_data.date_
                       and t.dif > t.dea
                     order by t.date_ asc)
             where rownum <= 1;
          EXCEPTION
            WHEN others THEN
              row_macd_gold_cross := null;
              exit;
          end;
        
          -- 获取mdl_boll_macd_gold_cross表中，某只股票的上一个交易记录
          /*begin
            select *
              into v_pre_acc_profit_loss
              from (select t.accumulative_profit_loss
                      from mdl_boll_macd_gold_cross t
                     where t.stock_code = v_code
                       and t.buy_date < row_stock_transaction_data.date_
                       and t.sell_date < row_macd_dead_cross.date_
                     order by t.buy_date desc)
             where rownum <= 1;
          EXCEPTION
            WHEN others THEN
              v_pre_acc_profit_loss := 100;
          end;*/
        
          -- 添加记录
          v_pre_acc_profit_loss := v_pre_acc_profit_loss * (1 +
                                   (row_stock_transaction_data.close_price -
                                   row_macd_gold_cross.close_price) /
                                   row_stock_transaction_data.close_price);
          insert into mdl_week_boll_macd_dead_cross
            (STOCK_CODE,
             BUY_DATE,
             BUY_PRICE,
             ACCUMULATIVE_PROFIT_LOSS,
             PROFIT_LOSS,
             SELL_DATE,
             SELL_PRICE)
          values
            (row_stock_transaction_data.code_,
             row_macd_gold_cross.date_,
             row_macd_gold_cross.close_price,
             v_pre_acc_profit_loss,
             (row_stock_transaction_data.close_price -
             row_macd_gold_cross.close_price) /
             row_stock_transaction_data.close_price * 100,
             row_stock_transaction_data.date_,
             row_stock_transaction_data.close_price);
        
          -- 重置
          v_dead_cross := 0;
          v_date       := row_macd_gold_cross.date_;
        end if;
      
      end loop;
      close cur_stock_week_up;
    
    end loop;
    close cur_stock_code;
    commit;
  end CAL_MDL_WEEK_BOLL_MACD_D_C;

  /*--------------- 计算周线级别布林带突破上轨后，close_price死叉ma5的算法 -----------------*/
  procedure CAL_MDL_WEEK_BOLL_C_P_MA5_D_C is
    -- 股票代码
    v_code varchar2(50);
    -- 日期
    v_date date := to_date('1997-01-01', 'yyyy-mm-dd');
    -- 行数
    v_row_num number;
    -- 是否有死叉，0表示没有，1表示有
    v_dead_cross number := 0;
    -- 累计盈利
    v_pre_acc_profit_loss number := 100;
    -- stock_week表的记录
    row_stock_week        stock_week%rowtype;
    row_first_stock_week  stock_week%rowtype;
    row_second_stock_week stock_week%rowtype;
    -- stock_transaction_data表的记录
    row_stock_transaction_data     stock_transaction_data%rowtype;
    row_close_price_ma5_gold_cross stock_transaction_data%rowtype;
    row_last_std                   stock_transaction_data%rowtype;
    -- 返回股票代码
    cursor cur_stock_code is
      select distinct t.code_ from stock_week t; -- where t.code_ = '603759';
    -- 某一只股票的最高价突破了布林带上轨
    cursor cur_stock_week_up is
      select *
        from stock_week t
       where t.highest_price > t.up
         and t.code_ = v_code
         and t.end_date > v_date
       order by t.begin_date asc;
    -- 某一只股票当前星期的记录，和下一个星期的记录
    cursor cur_two_stock_week is
      select *
        from (select *
                from stock_week t
               where t.code_ = v_code
                 and t.begin_date >= row_stock_week.begin_date
               order by t.begin_date asc)
       where rownum <= 2;
    -- 某一只股票在某个交易日之后和某个交易日之前的交易记录
    cursor cur_stock_transaction_data is
      select *
        from stock_transaction_data_all t
       where t.code_ = row_stock_week.code_
         and t.date_ > row_first_stock_week.end_date
         and t.date_ <= row_second_stock_week.end_date
       order by t.date_ asc;
  begin
    open cur_stock_code;
    loop
      fetch cur_stock_code
        into v_code;
      exit when cur_stock_code%notfound;
    
      -- 重置
      v_pre_acc_profit_loss := 100;
      v_date                := to_date('1997-01-01', 'yyyy-mm-dd');
    
      open cur_stock_week_up;
      loop
        fetch cur_stock_week_up
          into row_stock_week;
        exit when cur_stock_week_up%notfound;
        if row_stock_week.end_date < v_date then
          continue;
        end if;
      
        -- 如果不足两行，则说明这只股票已经计算完成
        select count(*)
          into v_row_num
          from (select *
                  from stock_week t
                 where t.code_ = v_code
                   and t.begin_date >= row_stock_week.begin_date
                 order by t.begin_date asc)
         where rownum <= 2;
        if v_row_num != 2 then
          exit;
        end if;
        -- 重置
        v_dead_cross          := 0;
        row_first_stock_week  := null;
        row_second_stock_week := null;
        -- 当前周和下一周
        for cur in cur_two_stock_week loop
          if row_first_stock_week.id_ is null then
            row_first_stock_week := cur;
          else
            row_second_stock_week := cur;
          end if;
        end loop;
        -- 如果下一周的最高价比当前周的最高价高，则放弃当前周
        if row_first_stock_week.highest_price <
           row_second_stock_week.highest_price then
          continue;
        end if;
      
        -- 判断下一周是否有close_price死叉ma5，如果没有就继续寻找下一个最高价突破布林带上轨的记录
        -- 注意此处只判断一周内是否有close_price死叉ma5，这样比较符合实盘交易的情况
        open cur_stock_transaction_data;
        loop
          fetch cur_stock_transaction_data
            into row_stock_transaction_data;
          exit when cur_stock_transaction_data%notfound;
          -- 死叉，卖出
          -- 查找前一天的交易记录
          select *
            into row_last_std
            from (select *
                    from stock_transaction_data_all t
                   where t.code_ = row_stock_transaction_data.code_
                     and t.date_ < row_stock_transaction_data.date_
                   order by t.date_ desc)
           where rownum <= 1;
          if row_last_std.close_price <= row_last_std.ma5 and
             row_stock_transaction_data.close_price <
             row_stock_transaction_data.ma5 then
            v_dead_cross := 1;
            exit;
          end if;
        end loop;
        close cur_stock_transaction_data;
        if v_dead_cross = 0 then
          continue;
        end if;
      
        -- 如果死叉出现，则开始寻找close_price金叉ma5的记录
        if v_dead_cross = 1 then
          -- 金叉，买入
          -- 某一只股票在某个交易日之后的第一个close_price金叉ma5。如果没有就从下一个最高价突破布林带上轨的记录开始
          begin
            select *
              into row_close_price_ma5_gold_cross
              from (select *
                      from stock_transaction_data_all t
                     where t.code_ = row_stock_transaction_data.code_
                       and t.date_ > row_stock_transaction_data.date_
                       and t.close_price > t.ma5
                     order by t.date_ asc)
             where rownum <= 1;
          EXCEPTION
            WHEN others THEN
              row_close_price_ma5_gold_cross := null;
              exit;
          end;
        
          -- 获取mdl_boll_macd_gold_cross表中，某只股票的上一个交易记录
          /*begin
            select *
              into v_pre_acc_profit_loss
              from (select t.accumulative_profit_loss
                      from mdl_boll_macd_gold_cross t
                     where t.stock_code = v_code
                       and t.buy_date < row_stock_transaction_data.date_
                       and t.sell_date < row_macd_dead_cross.date_
                     order by t.buy_date desc)
             where rownum <= 1;
          EXCEPTION
            WHEN others THEN
              v_pre_acc_profit_loss := 100;
          end;*/
        
          -- 添加记录
          v_pre_acc_profit_loss := v_pre_acc_profit_loss * (1 +
                                   (row_stock_transaction_data.close_price -
                                   row_close_price_ma5_gold_cross.close_price) /
                                   row_stock_transaction_data.close_price);
          insert into mdl_week_boll_c_p_ma5_d_c
            (STOCK_CODE,
             BUY_DATE,
             BUY_PRICE,
             ACCUMULATIVE_PROFIT_LOSS,
             PROFIT_LOSS,
             SELL_DATE,
             SELL_PRICE)
          values
            (row_stock_transaction_data.code_,
             row_close_price_ma5_gold_cross.date_,
             row_close_price_ma5_gold_cross.close_price,
             v_pre_acc_profit_loss,
             (row_stock_transaction_data.close_price -
             row_close_price_ma5_gold_cross.close_price) /
             row_stock_transaction_data.close_price * 100,
             row_stock_transaction_data.date_,
             row_stock_transaction_data.close_price);
        
          -- 重置
          v_dead_cross := 0;
          v_date       := row_close_price_ma5_gold_cross.date_;
        end if;
      
      end loop;
      close cur_stock_week_up;
    
    end loop;
    close cur_stock_code;
    commit;
  end CAL_MDL_WEEK_BOLL_C_P_MA5_D_C;

  /*--------------- 计算周线级别布林带突破上轨后，hei_kin_ashi下降趋势的算法 ---------------*/
  procedure CAL_MDL_WEEK_BOLL_H_K_A_D_U is
    -- 股票代码
    v_code varchar2(50);
    -- 日期
    v_date date := to_date('1997-01-01', 'yyyy-mm-dd');
    -- 行数
    v_row_num number;
    -- 是否有死叉，0表示没有，1表示有
    v_dead_cross number := 0;
    -- 累计盈利
    v_pre_acc_profit_loss number := 100;
    -- stock_week表的记录
    row_stock_week        stock_week%rowtype;
    row_first_stock_week  stock_week%rowtype;
    row_second_stock_week stock_week%rowtype;
    -- stock_transaction_data表的记录
    row_stock_transaction_data stock_transaction_data%rowtype;
    row_hei_kin_ashi_down_up   stock_transaction_data%rowtype;
    row_last_std               stock_transaction_data%rowtype;
    -- 返回股票代码
    cursor cur_stock_code is
      select distinct t.code_ from stock_week t; -- where t.code_ = '603759';
    -- 某一只股票的最高价突破了布林带上轨
    cursor cur_stock_week_up is
      select *
        from stock_week t
       where t.highest_price > t.up
         and t.code_ = v_code
         and t.end_date > v_date
       order by t.begin_date asc;
    -- 某一只股票当前星期的记录，和下一个星期的记录
    cursor cur_two_stock_week is
      select *
        from (select *
                from stock_week t
               where t.code_ = v_code
                 and t.begin_date >= row_stock_week.begin_date
               order by t.begin_date asc)
       where rownum <= 2;
    -- 某一只股票在某个交易日之后和某个交易日之前的交易记录
    cursor cur_stock_transaction_data is
      select *
        from stock_transaction_data_all t
       where t.code_ = row_stock_week.code_
         and t.date_ > row_first_stock_week.end_date
         and t.date_ <= row_second_stock_week.end_date
       order by t.date_ asc;
  begin
    open cur_stock_code;
    loop
      fetch cur_stock_code
        into v_code;
      exit when cur_stock_code%notfound;
    
      -- 重置
      v_pre_acc_profit_loss := 100;
      v_date                := to_date('1997-01-01', 'yyyy-mm-dd');
    
      open cur_stock_week_up;
      loop
        fetch cur_stock_week_up
          into row_stock_week;
        exit when cur_stock_week_up%notfound;
        if row_stock_week.end_date < v_date then
          continue;
        end if;
      
        -- 如果不足两行，则说明这只股票已经计算完成
        select count(*)
          into v_row_num
          from (select *
                  from stock_week t
                 where t.code_ = v_code
                   and t.begin_date >= row_stock_week.begin_date
                 order by t.begin_date asc)
         where rownum <= 2;
        if v_row_num != 2 then
          exit;
        end if;
        -- 重置
        v_dead_cross          := 0;
        row_first_stock_week  := null;
        row_second_stock_week := null;
        -- 当前周和下一周
        for cur in cur_two_stock_week loop
          if row_first_stock_week.id_ is null then
            row_first_stock_week := cur;
          else
            row_second_stock_week := cur;
          end if;
        end loop;
        -- 如果下一周的最高价比当前周的最高价高，则放弃当前周
        if row_first_stock_week.highest_price <
           row_second_stock_week.highest_price then
          continue;
        end if;
      
        -- 判断下一周是否有hei_kin_ashi下降趋势，如果没有就继续寻找下一个最高价突破布林带上轨的记录
        -- 注意此处只判断一周内是否有hei_kin_ashi下降趋势，这样比较符合实盘交易的情况
        open cur_stock_transaction_data;
        loop
          fetch cur_stock_transaction_data
            into row_stock_transaction_data;
          exit when cur_stock_transaction_data%notfound;
          -- 死叉，卖出
          -- 查找前一天的交易记录
          select *
            into row_last_std
            from (select *
                    from stock_transaction_data_all t
                   where t.code_ = row_stock_transaction_data.code_
                     and t.date_ < row_stock_transaction_data.date_
                   order by t.date_ desc)
           where rownum <= 1;
          if row_last_std.ha_close_price > row_last_std.ha_open_price and
             row_stock_transaction_data.ha_close_price <=
             row_stock_transaction_data.ha_open_price then
            v_dead_cross := 1;
            exit;
          end if;
        end loop;
        close cur_stock_transaction_data;
        if v_dead_cross = 0 then
          continue;
        end if;
      
        -- 如果hei_kin_ashi下降趋势出现，则开始寻找hei_kin_ashi下降趋势的记录
        if v_dead_cross = 1 then
          -- 金叉，买入
          -- 某一只股票在某个交易日之后的第一个hei_kin_ashi上升趋势。如果没有就从下一个最高价突破布林带上轨的记录开始
          begin
            select *
              into row_hei_kin_ashi_down_up
              from (select *
                      from stock_transaction_data_all t
                     where t.code_ = row_stock_transaction_data.code_
                       and t.date_ > row_stock_transaction_data.date_
                       and t.ha_close_price > t.ha_open_price
                     order by t.date_ asc)
             where rownum <= 1;
          EXCEPTION
            WHEN others THEN
              row_hei_kin_ashi_down_up := null;
              exit;
          end;
        
          -- 获取mdl_boll_macd_gold_cross表中，某只股票的上一个交易记录
          /*begin
            select *
              into v_pre_acc_profit_loss
              from (select t.accumulative_profit_loss
                      from mdl_boll_macd_gold_cross t
                     where t.stock_code = v_code
                       and t.buy_date < row_stock_transaction_data.date_
                       and t.sell_date < row_macd_dead_cross.date_
                     order by t.buy_date desc)
             where rownum <= 1;
          EXCEPTION
            WHEN others THEN
              v_pre_acc_profit_loss := 100;
          end;*/
        
          -- 添加记录
          v_pre_acc_profit_loss := v_pre_acc_profit_loss * (1 +
                                   (row_stock_transaction_data.close_price -
                                   row_hei_kin_ashi_down_up.close_price) /
                                   row_stock_transaction_data.close_price);
          insert into mdl_week_boll_H_K_A_DOWN_UP
            (STOCK_CODE,
             BUY_DATE,
             BUY_PRICE,
             ACCUMULATIVE_PROFIT_LOSS,
             PROFIT_LOSS,
             SELL_DATE,
             SELL_PRICE)
          values
            (row_stock_transaction_data.code_,
             row_hei_kin_ashi_down_up.date_,
             row_hei_kin_ashi_down_up.close_price,
             v_pre_acc_profit_loss,
             (row_stock_transaction_data.close_price -
             row_hei_kin_ashi_down_up.close_price) /
             row_stock_transaction_data.close_price * 100,
             row_stock_transaction_data.date_,
             row_stock_transaction_data.close_price);
        
          -- 重置
          v_dead_cross := 0;
          v_date       := row_hei_kin_ashi_down_up.date_;
        end if;
      
      end loop;
      close cur_stock_week_up;
    
    end loop;
    close cur_stock_code;
    commit;
  end CAL_MDL_WEEK_BOLL_H_K_A_D_U;

  /*--------------- 计算周线级别布林带突破上轨后，kd死叉的算法 ---------------*/
  procedure CAL_MDL_WEEK_BOLL_KD_D_C is
    -- 股票代码
    v_code varchar2(50);
    -- 日期
    v_date date := to_date('1997-01-01', 'yyyy-mm-dd');
    -- 行数
    v_row_num number;
    -- 是否有死叉，0表示没有，1表示有
    v_dead_cross number := 0;
    -- 累计盈利
    v_pre_acc_profit_loss number := 100;
    -- stock_week表的记录
    row_stock_week        stock_week%rowtype;
    row_first_stock_week  stock_week%rowtype;
    row_second_stock_week stock_week%rowtype;
    -- stock_transaction_data表的记录
    row_stock_transaction_data stock_transaction_data%rowtype;
    row_kd_dead_cross          stock_transaction_data%rowtype;
    row_last_std               stock_transaction_data%rowtype;
    -- 返回股票代码
    cursor cur_stock_code is
      select distinct t.code_ from stock_week t; -- where t.code_ = '603759';
    -- 某一只股票的最高价突破了布林带上轨
    cursor cur_stock_week_up is
      select *
        from stock_week t
       where t.highest_price > t.up
         and t.code_ = v_code
         and t.end_date > v_date
       order by t.begin_date asc;
    -- 某一只股票当前星期的记录，和下一个星期的记录
    cursor cur_two_stock_week is
      select *
        from (select *
                from stock_week t
               where t.code_ = v_code
                 and t.begin_date >= row_stock_week.begin_date
               order by t.begin_date asc)
       where rownum <= 2;
    -- 某一只股票在某个交易日之后和某个交易日之前的交易记录
    cursor cur_stock_transaction_data is
      select *
        from stock_transaction_data_all t
       where t.code_ = row_stock_week.code_
         and t.date_ > row_first_stock_week.end_date
         and t.date_ <= row_second_stock_week.end_date
       order by t.date_ asc;
  begin
    open cur_stock_code;
    loop
      fetch cur_stock_code
        into v_code;
      exit when cur_stock_code%notfound;
    
      -- 重置
      v_pre_acc_profit_loss := 100;
      v_date                := to_date('1997-01-01', 'yyyy-mm-dd');
    
      open cur_stock_week_up;
      loop
        fetch cur_stock_week_up
          into row_stock_week;
        exit when cur_stock_week_up%notfound;
        if row_stock_week.end_date < v_date then
          continue;
        end if;
      
        -- 如果不足两行，则说明这只股票已经计算完成
        select count(*)
          into v_row_num
          from (select *
                  from stock_week t
                 where t.code_ = v_code
                   and t.begin_date >= row_stock_week.begin_date
                 order by t.begin_date asc)
         where rownum <= 2;
        if v_row_num != 2 then
          exit;
        end if;
        -- 重置
        v_dead_cross          := 0;
        row_first_stock_week  := null;
        row_second_stock_week := null;
        -- 当前周和下一周
        for cur in cur_two_stock_week loop
          if row_first_stock_week.id_ is null then
            row_first_stock_week := cur;
          else
            row_second_stock_week := cur;
          end if;
        end loop;
        -- 如果下一周的最高价比当前周的最高价高，则放弃当前周
        if row_first_stock_week.highest_price <
           row_second_stock_week.highest_price then
          continue;
        end if;
      
        -- 判断下一周是否有kd死叉，如果没有就继续寻找下一个最高价突破布林带上轨的记录
        -- 注意此处只判断一周内是否有kd死叉，这样比较符合实盘交易的情况
        open cur_stock_transaction_data;
        loop
          fetch cur_stock_transaction_data
            into row_stock_transaction_data;
          exit when cur_stock_transaction_data%notfound;
          -- 死叉，卖出
          -- 查找前一天的交易记录
          select *
            into row_last_std
            from (select *
                    from stock_transaction_data_all t
                   where t.code_ = row_stock_transaction_data.code_
                     and t.date_ < row_stock_transaction_data.date_
                   order by t.date_ desc)
           where rownum <= 1;
          if row_last_std.k <= row_last_std.d and
             row_stock_transaction_data.k < row_stock_transaction_data.d then
            v_dead_cross := 1;
            exit;
          end if;
        end loop;
        close cur_stock_transaction_data;
        if v_dead_cross = 0 then
          continue;
        end if;
      
        -- 如果kd死叉出现，则开始寻找kd金叉的记录
        if v_dead_cross = 1 then
          -- 金叉， 买入
          -- 某一只股票在某个交易日之后的第一个kd金叉。如果没有就从下一个最高价突破布林带上轨的记录开始
          begin
            select *
              into row_kd_dead_cross
              from (select *
                      from stock_transaction_data_all t
                     where t.code_ = row_stock_transaction_data.code_
                       and t.date_ > row_stock_transaction_data.date_
                       and t.k > t.d
                     order by t.date_ asc)
             where rownum <= 1;
          EXCEPTION
            WHEN others THEN
              row_kd_dead_cross := null;
              exit;
          end;
        
          -- 获取mdl_boll_macd_gold_cross表中，某只股票的上一个交易记录
          /*begin
            select *
              into v_pre_acc_profit_loss
              from (select t.accumulative_profit_loss
                      from mdl_boll_macd_gold_cross t
                     where t.stock_code = v_code
                       and t.buy_date < row_stock_transaction_data.date_
                       and t.sell_date < row_macd_dead_cross.date_
                     order by t.buy_date desc)
             where rownum <= 1;
          EXCEPTION
            WHEN others THEN
              v_pre_acc_profit_loss := 100;
          end;*/
        
          -- 添加记录
          v_pre_acc_profit_loss := v_pre_acc_profit_loss * (1 +
                                   (row_stock_transaction_data.close_price -
                                   row_kd_dead_cross.close_price) /
                                   row_stock_transaction_data.close_price);
          insert into mdl_week_boll_kd_dead_cross
            (STOCK_CODE,
             BUY_DATE,
             BUY_PRICE,
             ACCUMULATIVE_PROFIT_LOSS,
             PROFIT_LOSS,
             SELL_DATE,
             SELL_PRICE)
          values
            (row_stock_transaction_data.code_,
             row_kd_dead_cross.date_,
             row_kd_dead_cross.close_price,
             v_pre_acc_profit_loss,
             (row_stock_transaction_data.close_price -
             row_kd_dead_cross.close_price) /
             row_stock_transaction_data.close_price * 100,
             row_stock_transaction_data.date_,
             row_stock_transaction_data.close_price);
        
          -- 重置
          v_dead_cross := 0;
          v_date       := row_kd_dead_cross.date_;
        end if;
      
      end loop;
      close cur_stock_week_up;
    
    end loop;
    close cur_stock_code;
    commit;
  end CAL_MDL_WEEK_BOLL_KD_D_C;

  /*-- 查询周线级别最高价突破布林带上轨的百分比和MACD死叉交易收益率的散点图，
  x轴是收益率，y轴是(前一周最高价-布林带上轨)/布林带上轨，
  全称find_week_heighest_price_up_boll_percent_and_macd_dead_cross_profit --*/
  procedure find_w_h_p_u_b_p_a_macd_d_c_p(p_begin_date          in varchar2,
                                          p_end_date            in varchar2,
                                          p_t_w_b_u_p_l_p_array out T_WEEK_BOLL_U_D_P_L_P_ARRAY) is
    -- mdl_week_boll_macd_dead_cross类型
    row_mdl_week_boll_macd_d_c mdl_week_boll_macd_dead_cross%Rowtype;
    -- stock_week类型
    row_stock_week        stock_week%Rowtype;
    v_t_week_boll_u_d_p_l T_WEEK_BOLL_U_D_P_L_PERCENT;
    -- 在某段时间之内的所有交易
    cursor cur_m_w_b_macd_d_c is
      select *
        from mdl_week_boll_macd_dead_cross t
       where t.sell_date between to_date(p_begin_date, 'yyyy-mm-dd') and
             to_date(p_end_date, 'yyyy-mm-dd');
    -- 某个交易记录的上一周数据
    cursor cur_stock_week is
      select *
        from (select *
                from stock_week sw
               where sw.end_date < row_mdl_week_boll_macd_d_c.sell_date
                 and sw.code_ = row_mdl_week_boll_macd_d_c.stock_code
               order by sw.begin_date desc)
       where rownum <= 1;
  begin
    -- 初始化
    p_t_w_b_u_p_l_p_array := T_WEEK_BOLL_U_D_P_L_P_ARRAY();
  
    open cur_m_w_b_macd_d_c;
    loop
      fetch cur_m_w_b_macd_d_c
        into row_mdl_week_boll_macd_d_c;
      exit when cur_m_w_b_macd_d_c%notfound;
    
      open cur_stock_week;
      loop
        fetch cur_stock_week
          into row_stock_week;
        exit when cur_stock_week%notfound;
      
        -- 保存
        v_t_week_boll_u_d_p_l := T_WEEK_BOLL_U_D_P_L_PERCENT(row_mdl_week_boll_macd_d_c.profit_loss,
                                                             (row_stock_week.highest_price -
                                                             row_stock_week.up) /
                                                             row_stock_week.up * 100);
        p_t_w_b_u_p_l_p_array.extend;
        p_t_w_b_u_p_l_p_array(p_t_w_b_u_p_l_p_array.count) := v_t_week_boll_u_d_p_l;
      
      end loop;
      close cur_stock_week;
    
    end loop;
    close cur_m_w_b_macd_d_c;
  end find_w_h_p_u_b_p_a_macd_d_c_p;

  /*-- 查询周线级别最低价突破布林带下轨的百分比和MACD金叉交易收益率的散点图，
  x轴是收益率，y轴是(前一周最低价-布林带下轨)/布林带下轨，
  全称find_week_lowest_price_dn_boll_percent_and_macd_gold_cross_profit --*/
  procedure find_w_l_p_d_b_p_a_macd_g_c_p(p_begin_date          in varchar2,
                                          p_end_date            in varchar2,
                                          p_t_w_b_u_p_l_p_array out T_WEEK_BOLL_U_D_P_L_P_ARRAY) is
    -- mdl_week_boll_macd_gold_cross类型
    row_mdl_week_boll_macd_g_c mdl_week_boll_macd_gold_cross%Rowtype;
    -- stock_week类型
    row_stock_week        stock_week%Rowtype;
    v_t_week_boll_u_d_p_l T_WEEK_BOLL_U_D_P_L_PERCENT;
    -- 在某段时间之内的所有交易
    cursor cur_m_w_b_macd_g_c is
      select *
        from mdl_week_boll_macd_gold_cross t
       where t.buy_date between to_date(p_begin_date, 'yyyy-mm-dd') and
             to_date(p_end_date, 'yyyy-mm-dd');
    -- 某个交易记录的上一周数据
    cursor cur_stock_week is
      select *
        from (select *
                from stock_week sw
               where sw.end_date < row_mdl_week_boll_macd_g_c.buy_date
                 and sw.code_ = row_mdl_week_boll_macd_g_c.stock_code
               order by sw.begin_date desc)
       where rownum <= 1;
  begin
    -- 初始化
    p_t_w_b_u_p_l_p_array := T_WEEK_BOLL_U_D_P_L_P_ARRAY();
  
    open cur_m_w_b_macd_g_c;
    loop
      fetch cur_m_w_b_macd_g_c
        into row_mdl_week_boll_macd_g_c;
      exit when cur_m_w_b_macd_g_c%notfound;
    
      open cur_stock_week;
      loop
        fetch cur_stock_week
          into row_stock_week;
        exit when cur_stock_week%notfound;
      
        -- 保存
        v_t_week_boll_u_d_p_l := T_WEEK_BOLL_U_D_P_L_PERCENT(row_mdl_week_boll_macd_g_c.profit_loss,
                                                             (row_stock_week.lowest_price -
                                                             row_stock_week.dn_) /
                                                             row_stock_week.dn_ * 100);
        p_t_w_b_u_p_l_p_array.extend;
        p_t_w_b_u_p_l_p_array(p_t_w_b_u_p_l_p_array.count) := v_t_week_boll_u_d_p_l;
      
      end loop;
      close cur_stock_week;
    
    end loop;
    close cur_m_w_b_macd_g_c;
  end find_w_l_p_d_b_p_a_macd_g_c_p;

  /*-- 查询周线级别最高价突破布林带上轨的百分比和close_price死叉ma5交易收益率的散点图，
  x轴是收益率，y轴是(前一周最高价-布林带上轨)/布林带上轨，
  全称find_week_heighest_price_up_boll_percent_and_close_price_dead_cross_ma5_profit --*/
  procedure find_w_h_p_u_b_p_a_c_p_d_c_5_p(p_begin_date          in varchar2,
                                           p_end_date            in varchar2,
                                           p_t_w_b_u_p_l_p_array out T_WEEK_BOLL_U_D_P_L_P_ARRAY) is
    -- mdl_week_boll_c_p_ma5_d_c类型
    row_mdl_week_boll_c_p_ma5_d_c mdl_week_boll_c_p_ma5_d_c%Rowtype;
    -- stock_week类型
    row_stock_week        stock_week%Rowtype;
    v_t_week_boll_u_d_p_l T_WEEK_BOLL_U_D_P_L_PERCENT;
    -- 在某段时间之内的所有交易
    cursor cur_m_w_b_c_p_ma5_d_c is
      select *
        from mdl_week_boll_c_p_ma5_d_c t
       where t.sell_date between to_date(p_begin_date, 'yyyy-mm-dd') and
             to_date(p_end_date, 'yyyy-mm-dd');
    -- 某个交易记录的上一周数据
    cursor cur_stock_week is
      select *
        from (select *
                from stock_week sw
               where sw.end_date < row_mdl_week_boll_c_p_ma5_d_c.sell_date
                 and sw.code_ = row_mdl_week_boll_c_p_ma5_d_c.stock_code
               order by sw.begin_date desc)
       where rownum <= 1;
  begin
    -- 初始化
    p_t_w_b_u_p_l_p_array := T_WEEK_BOLL_U_D_P_L_P_ARRAY();
  
    open cur_m_w_b_c_p_ma5_d_c;
    loop
      fetch cur_m_w_b_c_p_ma5_d_c
        into row_mdl_week_boll_c_p_ma5_d_c;
      exit when cur_m_w_b_c_p_ma5_d_c%notfound;
    
      open cur_stock_week;
      loop
        fetch cur_stock_week
          into row_stock_week;
        exit when cur_stock_week%notfound;
      
        -- 保存
        v_t_week_boll_u_d_p_l := T_WEEK_BOLL_U_D_P_L_PERCENT(row_mdl_week_boll_c_p_ma5_d_c.profit_loss,
                                                             (row_stock_week.highest_price -
                                                             row_stock_week.up) /
                                                             row_stock_week.up * 100);
        p_t_w_b_u_p_l_p_array.extend;
        p_t_w_b_u_p_l_p_array(p_t_w_b_u_p_l_p_array.count) := v_t_week_boll_u_d_p_l;
      
      end loop;
      close cur_stock_week;
    
    end loop;
    close cur_m_w_b_c_p_ma5_d_c;
  end find_w_h_p_u_b_p_a_c_p_d_c_5_p;

  /*-- 查询周线级别最低价突破布林带下轨的百分比和close_price金叉MA5易收益率的散点图，
  x轴是收益率，y轴是(前一周最低价-布林带下轨)/布林带下轨，
  全称find_week_lowest_price_dn_boll_percent_and_close_price_gold_cross_ma5_profit --*/
  procedure find_w_l_p_d_b_p_a_c_p_g_c_5_p(p_begin_date          in varchar2,
                                           p_end_date            in varchar2,
                                           p_t_w_b_u_p_l_p_array out T_WEEK_BOLL_U_D_P_L_P_ARRAY) is
    -- mdl_week_boll_c_p_ma5_g_c类型
    row_mdl_week_boll_c_p_ma5_g_c mdl_week_boll_c_p_ma5_g_c%Rowtype;
    -- stock_week类型
    row_stock_week        stock_week%Rowtype;
    v_t_week_boll_u_d_p_l T_WEEK_BOLL_U_D_P_L_PERCENT;
    -- 在某段时间之内的所有交易
    cursor cur_m_w_b_c_p_ma5_g_c is
      select *
        from mdl_week_boll_c_p_ma5_g_c t
       where t.buy_date between to_date(p_begin_date, 'yyyy-mm-dd') and
             to_date(p_end_date, 'yyyy-mm-dd');
    -- 某个交易记录的上一周数据
    cursor cur_stock_week is
      select *
        from (select *
                from stock_week sw
               where sw.end_date < row_mdl_week_boll_c_p_ma5_g_c.buy_date
                 and sw.code_ = row_mdl_week_boll_c_p_ma5_g_c.stock_code
               order by sw.begin_date desc)
       where rownum <= 1;
  begin
    -- 初始化
    p_t_w_b_u_p_l_p_array := T_WEEK_BOLL_U_D_P_L_P_ARRAY();
  
    open cur_m_w_b_c_p_ma5_g_c;
    loop
      fetch cur_m_w_b_c_p_ma5_g_c
        into row_mdl_week_boll_c_p_ma5_g_c;
      exit when cur_m_w_b_c_p_ma5_g_c%notfound;
    
      open cur_stock_week;
      loop
        fetch cur_stock_week
          into row_stock_week;
        exit when cur_stock_week%notfound;
      
        -- 保存
        v_t_week_boll_u_d_p_l := T_WEEK_BOLL_U_D_P_L_PERCENT(row_mdl_week_boll_c_p_ma5_g_c.profit_loss,
                                                             (row_stock_week.lowest_price -
                                                             row_stock_week.dn_) /
                                                             row_stock_week.dn_ * 100);
        p_t_w_b_u_p_l_p_array.extend;
        p_t_w_b_u_p_l_p_array(p_t_w_b_u_p_l_p_array.count) := v_t_week_boll_u_d_p_l;
      
      end loop;
      close cur_stock_week;
    
    end loop;
    close cur_m_w_b_c_p_ma5_g_c;
  end find_w_l_p_d_b_p_a_c_p_g_c_5_p;

  /*-- 查询周线级别最高价突破布林带上轨的百分比和hei_kin_ashi下跌趋势交易收益率的散点图，
  x轴是收益率，y轴是(前一周最高价-布林带上轨)/布林带上轨，
  全称find_week_heighest_price_up_boll_percent_and_hei_kin_ashi_down_up_profit --*/
  procedure find_w_h_p_u_b_p_a_h_k_a_d_u_p(p_begin_date          in varchar2,
                                           p_end_date            in varchar2,
                                           p_t_w_b_u_p_l_p_array out T_WEEK_BOLL_U_D_P_L_P_ARRAY) is
    -- mdl_week_boll_h_k_a_down_up类型
    row_mdl_week_boll_h_k_a_d_u mdl_week_boll_h_k_a_down_up%Rowtype;
    -- stock_week类型
    row_stock_week        stock_week%Rowtype;
    v_t_week_boll_u_d_p_l T_WEEK_BOLL_U_D_P_L_PERCENT;
    -- 在某段时间之内的所有交易
    cursor cur_m_w_b_h_k_a_down_up is
      select *
        from mdl_week_boll_h_k_a_down_up t
       where t.sell_date between to_date(p_begin_date, 'yyyy-mm-dd') and
             to_date(p_end_date, 'yyyy-mm-dd');
    -- 某个交易记录的上一周数据
    cursor cur_stock_week is
      select *
        from (select *
                from stock_week sw
               where sw.end_date < row_mdl_week_boll_h_k_a_d_u.sell_date
                 and sw.code_ = row_mdl_week_boll_h_k_a_d_u.stock_code
               order by sw.begin_date desc)
       where rownum <= 1;
  begin
    -- 初始化
    p_t_w_b_u_p_l_p_array := T_WEEK_BOLL_U_D_P_L_P_ARRAY();
  
    open cur_m_w_b_h_k_a_down_up;
    loop
      fetch cur_m_w_b_h_k_a_down_up
        into row_mdl_week_boll_h_k_a_d_u;
      exit when cur_m_w_b_h_k_a_down_up%notfound;
    
      open cur_stock_week;
      loop
        fetch cur_stock_week
          into row_stock_week;
        exit when cur_stock_week%notfound;
      
        -- 保存
        v_t_week_boll_u_d_p_l := T_WEEK_BOLL_U_D_P_L_PERCENT(row_mdl_week_boll_h_k_a_d_u.profit_loss,
                                                             (row_stock_week.highest_price -
                                                             row_stock_week.up) /
                                                             row_stock_week.up * 100);
        p_t_w_b_u_p_l_p_array.extend;
        p_t_w_b_u_p_l_p_array(p_t_w_b_u_p_l_p_array.count) := v_t_week_boll_u_d_p_l;
      
      end loop;
      close cur_stock_week;
    
    end loop;
    close cur_m_w_b_h_k_a_down_up;
  end find_w_h_p_u_b_p_a_h_k_a_d_u_p;

  /*-- 查询周线级别最低价突破布林带下轨的百分比和hei_kin_ashi上涨趋势交易收益率的散点图，
  x轴是收益率，y轴是(前一周最低价-布林带下轨)/布林带下轨，
  全称find_week_lowest_price_dn_boll_percent_and_hei_kin_ashi_up_down_profit --*/
  procedure find_w_l_p_d_b_p_a_h_k_a_u_d_p(p_begin_date          in varchar2,
                                           p_end_date            in varchar2,
                                           p_t_w_b_u_p_l_p_array out T_WEEK_BOLL_U_D_P_L_P_ARRAY) is
    -- mdl_week_boll_h_k_a_up_down类型
    row_mdl_week_boll_h_k_a_u_d mdl_week_boll_h_k_a_up_down%Rowtype;
    -- stock_week类型
    row_stock_week        stock_week%Rowtype;
    v_t_week_boll_u_d_p_l T_WEEK_BOLL_U_D_P_L_PERCENT;
    -- 在某段时间之内的所有交易
    cursor cur_m_w_b_h_k_a_up_down is
      select *
        from mdl_week_boll_h_k_a_up_down t
       where t.buy_date between to_date(p_begin_date, 'yyyy-mm-dd') and
             to_date(p_end_date, 'yyyy-mm-dd');
    -- 某个交易记录的上一周数据
    cursor cur_stock_week is
      select *
        from (select *
                from stock_week sw
               where sw.end_date < row_mdl_week_boll_h_k_a_u_d.buy_date
                 and sw.code_ = row_mdl_week_boll_h_k_a_u_d.stock_code
               order by sw.begin_date desc)
       where rownum <= 1;
  begin
    -- 初始化
    p_t_w_b_u_p_l_p_array := T_WEEK_BOLL_U_D_P_L_P_ARRAY();
  
    open cur_m_w_b_h_k_a_up_down;
    loop
      fetch cur_m_w_b_h_k_a_up_down
        into row_mdl_week_boll_h_k_a_u_d;
      exit when cur_m_w_b_h_k_a_up_down%notfound;
    
      open cur_stock_week;
      loop
        fetch cur_stock_week
          into row_stock_week;
        exit when cur_stock_week%notfound;
      
        -- 保存
        v_t_week_boll_u_d_p_l := T_WEEK_BOLL_U_D_P_L_PERCENT(row_mdl_week_boll_h_k_a_u_d.profit_loss,
                                                             (row_stock_week.lowest_price -
                                                             row_stock_week.dn_) /
                                                             row_stock_week.dn_ * 100);
        p_t_w_b_u_p_l_p_array.extend;
        p_t_w_b_u_p_l_p_array(p_t_w_b_u_p_l_p_array.count) := v_t_week_boll_u_d_p_l;
      
      end loop;
      close cur_stock_week;
    
    end loop;
    close cur_m_w_b_h_k_a_up_down;
  end find_w_l_p_d_b_p_a_h_k_a_u_d_p;

  /*-- 查询周线级别最高价突破布林带上轨的百分比和KD死叉交易收益率的散点图，
  x轴是收益率，y轴是(前一周最高价-布林带上轨)/布林带上轨，
  全称find_week_heighest_price_up_boll_percent_and_kd_dead_cross_profit --*/
  procedure find_w_h_p_u_b_p_a_kd_d_c_p(p_begin_date          in varchar2,
                                        p_end_date            in varchar2,
                                        p_t_w_b_u_p_l_p_array out T_WEEK_BOLL_U_D_P_L_P_ARRAY) is
    -- mdl_week_boll_kd_gold_cross类型
    row_mdl_week_boll_kd_d_c mdl_week_boll_kd_dead_cross%Rowtype;
    -- stock_week类型
    row_stock_week        stock_week%Rowtype;
    v_t_week_boll_u_d_p_l T_WEEK_BOLL_U_D_P_L_PERCENT;
    -- 在某段时间之内的所有交易
    cursor cur_m_w_b_kd_g_c is
      select *
        from mdl_week_boll_kd_dead_cross t
       where t.sell_date between to_date(p_begin_date, 'yyyy-mm-dd') and
             to_date(p_end_date, 'yyyy-mm-dd');
    -- 某个交易记录的上一周数据
    cursor cur_stock_week is
      select *
        from (select *
                from stock_week sw
               where sw.end_date < row_mdl_week_boll_kd_d_c.sell_date
                 and sw.code_ = row_mdl_week_boll_kd_d_c.stock_code
               order by sw.begin_date desc)
       where rownum <= 1;
  begin
    -- 初始化
    p_t_w_b_u_p_l_p_array := T_WEEK_BOLL_U_D_P_L_P_ARRAY();
  
    open cur_m_w_b_kd_g_c;
    loop
      fetch cur_m_w_b_kd_g_c
        into row_mdl_week_boll_kd_d_c;
      exit when cur_m_w_b_kd_g_c%notfound;
    
      open cur_stock_week;
      loop
        fetch cur_stock_week
          into row_stock_week;
        exit when cur_stock_week%notfound;
      
        -- 保存
        v_t_week_boll_u_d_p_l := T_WEEK_BOLL_U_D_P_L_PERCENT(row_mdl_week_boll_kd_d_c.profit_loss,
                                                             (row_stock_week.highest_price -
                                                             row_stock_week.up) /
                                                             row_stock_week.up * 100);
        p_t_w_b_u_p_l_p_array.extend;
        p_t_w_b_u_p_l_p_array(p_t_w_b_u_p_l_p_array.count) := v_t_week_boll_u_d_p_l;
      
      end loop;
      close cur_stock_week;
    
    end loop;
    close cur_m_w_b_kd_g_c;
  end find_w_h_p_u_b_p_a_kd_d_c_p;

  /*-- 查询周线级别最低价突破布林带下轨的百分比和KD金叉交易收益率的散点图，
  x轴是收益率，y轴是(前一周最低价-布林带下轨)/布林带下轨，
  全称find_week_lowest_price_dn_boll_percent_and_kd_gold_cross_profit --*/
  procedure find_w_l_p_d_b_p_a_kd_g_c_p(p_begin_date          in varchar2,
                                        p_end_date            in varchar2,
                                        p_t_w_b_u_p_l_p_array out T_WEEK_BOLL_U_D_P_L_P_ARRAY) is
    -- mdl_week_boll_kd_gold_cross类型
    row_mdl_week_boll_kd_g_c mdl_week_boll_kd_gold_cross%Rowtype;
    -- stock_week类型
    row_stock_week        stock_week%Rowtype;
    v_t_week_boll_u_d_p_l T_WEEK_BOLL_U_D_P_L_PERCENT;
    -- 在某段时间之内的所有交易
    cursor cur_m_w_b_kd_g_c is
      select *
        from mdl_week_boll_kd_gold_cross t
       where t.buy_date between to_date(p_begin_date, 'yyyy-mm-dd') and
             to_date(p_end_date, 'yyyy-mm-dd');
    -- 某个交易记录的上一周数据
    cursor cur_stock_week is
      select *
        from (select *
                from stock_week sw
               where sw.end_date < row_mdl_week_boll_kd_g_c.buy_date
                 and sw.code_ = row_mdl_week_boll_kd_g_c.stock_code
               order by sw.begin_date desc)
       where rownum <= 1;
  begin
    -- 初始化
    p_t_w_b_u_p_l_p_array := T_WEEK_BOLL_U_D_P_L_P_ARRAY();
  
    open cur_m_w_b_kd_g_c;
    loop
      fetch cur_m_w_b_kd_g_c
        into row_mdl_week_boll_kd_g_c;
      exit when cur_m_w_b_kd_g_c%notfound;
    
      open cur_stock_week;
      loop
        fetch cur_stock_week
          into row_stock_week;
        exit when cur_stock_week%notfound;
      
        -- 保存
        v_t_week_boll_u_d_p_l := T_WEEK_BOLL_U_D_P_L_PERCENT(row_mdl_week_boll_kd_g_c.profit_loss,
                                                             (row_stock_week.lowest_price -
                                                             row_stock_week.dn_) /
                                                             row_stock_week.dn_ * 100);
        p_t_w_b_u_p_l_p_array.extend;
        p_t_w_b_u_p_l_p_array(p_t_w_b_u_p_l_p_array.count) := v_t_week_boll_u_d_p_l;
      
      end loop;
      close cur_stock_week;
    
    end loop;
    close cur_m_w_b_kd_g_c;
  end find_w_l_p_d_b_p_a_kd_g_c_p;
end PKG_MODEL_WEEK;